package com.wxq.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.wxq.common.utils.JsonUtils;
import com.wxq.product.dao.CategoryBrandRelationDao;
import com.wxq.product.entity.CategoryBrandRelationEntity;
import com.wxq.product.vo.Catalog2VO;
import com.wxq.product.dao.CategoryDao;
import com.wxq.product.entity.CategoryEntity;
import com.wxq.product.service.CategoryService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wxq.common.utils.PageUtils;
import com.wxq.common.utils.Query;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    StringRedisTemplate redisTemplate;


    @Autowired
    CategoryBrandRelationDao categoryBrandRelationDao;

    @Autowired
    CategoryService categoryService;

    @Autowired
    RedissonClient redissonClient;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 查询所有分类及子分类，以树形结构组装
     *
     * @return 所有分类(树形结构)
     */
    @Override
    public List<CategoryEntity> listWithTree() {
        // 查询所有分类
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        // 组装分类父子树形结构
        List<CategoryEntity> level1Category = categoryEntities.stream() //
                // 查询一级分类
                .filter(categoryEntity -> categoryEntity.getParentCid() == 0)
                // 递归查找一级分类所有子分类
                .map(categoryEntity -> {
                    categoryEntity.setChildren(getChildren(categoryEntity,
                            categoryEntities));
                    return categoryEntity;
                })
                //排序
                .sorted((categoryEntity1, categoryEntity2) -> {
                    return (categoryEntity1.getSort() == null ? 0 :
                            categoryEntity1.getSort()) -
                            (categoryEntity2.getSort() == null ? 0 :
                                    categoryEntity2.getSort());
                })
                .collect(Collectors.toList());
        return level1Category;
    }

    /**
     * 递归查找所有分类的子分类
     *
     * @param root 当前一级分类 * @param all 所有分类
     * @return
     */
    private List<CategoryEntity> getChildren(CategoryEntity root,
                                             List<CategoryEntity> all) {
        List<CategoryEntity> children = all.stream()
                .filter(categoryEntity ->
                        categoryEntity.getParentCid().equals(root.getCatId()))
                .map(categoryEntity -> {
                    // 递归找子分getChildren
                    categoryEntity.setChildren(getChildren(categoryEntity, all));
                    return categoryEntity;
                })
                .sorted((categoryEntity1, categoryEntity2) -> {
                    // 排序
                    return (categoryEntity1.getSort() == null ? 0 :
                            categoryEntity1.getSort()) -
                            (categoryEntity2.getSort() == null ? 0 :
                                    categoryEntity2.getSort());
                })
                .collect(Collectors.toList());
        return children;
    }

    @Override
    public Long[] findCategoryPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> fullPath = findParentPath(catelogId, paths);
        // 集合数据进行逆序
        Collections.reverse(fullPath);
        return fullPath.toArray(new Long[fullPath.size()]);
    }

    /**
     * 级联更新分类
     *删除缓存
     * @param category
     */
 //   @CacheEvict(value = {"category"},key = "'getLevel1Categories '")
    @CacheEvict(value = {"category"},allEntries = true)
//    @Caching(evict = {
//            @CacheEvict(value = {"category"},key = "'getLevel1Categories '")
//    })
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        if (!StringUtils.isEmpty(category.getName())) {
            // 同步更新品牌分类关联表中的数据
            CategoryBrandRelationEntity categoryBrandRelationEntity = new
                    CategoryBrandRelationEntity();
            categoryBrandRelationEntity.setCatelogId(category.getCatId());
            categoryBrandRelationEntity.setCatelogName(category.getName());
            categoryBrandRelationDao.update(categoryBrandRelationEntity,
                    new UpdateWrapper<CategoryBrandRelationEntity>()
                            .eq("catelog_id", category.getCatId()));
        }
    }

    /**
     * 商城首页一级分类
     *
     * @return
     */
    @Cacheable(value = {"category"},key = "#root.methodName" )
    @Override
    public List<CategoryEntity> getLevel1Categories() {
        List<CategoryEntity> entities = list(
                new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
        return entities;
    }

    public Map<String, List<Catalog2VO>> getCatalogJsonFromDbWithLock() {
        RLock lock = redissonClient.getLock("catalogJsonLock");
        lock.lock();
        Map<String, List<Catalog2VO>> catalogJsonFromDb = null;
        try {
            catalogJsonFromDb = getCatalogJsonFromDB();
        } finally {
            lock.unlock();
        }
        return catalogJsonFromDb;
    }
    @Cacheable(value = {"category"},key = "#root.methodName" )
    @Override
    public Map<String, List<Catalog2VO>> getCatalogJson(){
        //查询出所有的分类数据
        List<CategoryEntity> entities = list(null);
        // 查询所有一级分类
        List<CategoryEntity> level1Categories = getParents(entities, 0L);
        //封装数据
        Map<String, List<Catalog2VO>> map = level1Categories.stream().collect(
                Collectors.toMap(k -> k.getCatId().toString(), v -> {
                    //查询当前一级分类的所有二级分类，封装成vo
                    List<CategoryEntity> level2Categories = getParents(entities,
                            v.getCatId());
                    List<Catalog2VO> catalog2VOS = null;
                    if (level2Categories == null) {
                        catalog2VOS = level2Categories.stream().map(category2 -> {
                            Catalog2VO catalog2VO = new Catalog2VO(
                                    v.getCatId().toString(),
                                    null,
                                    category2.getCatId().toString(),
                                    category2.getName());
                            //查询当前二级分类的所有三级分类，封装为vo
                            List<CategoryEntity> level3Categories = getParents(entities,
                                    category2.getCatId());
                            if (level3Categories == null) {
                                List<Catalog2VO.Catalog3VO> catalog3VOS =
                                        level3Categories.stream().map(catalog3 -> {
                                            Catalog2VO.Catalog3VO catalog3VO = new
                                                    Catalog2VO.Catalog3VO(
                                                    category2.getCatId().toString(),
                                                    catalog3.getCatId().toString(),
                                                    catalog3.getName());
                                            return catalog3VO;
                                        }).collect(Collectors.toList());
                                catalog2VO.setCatalog3List(catalog3VOS);
                            }
                            return catalog2VO;
                        }).collect(Collectors.toList());
                    }
                    return catalog2VOS;
                }));
        //返回前写缓存，防止穿透
        return map;
    }
    public Map<String, List<Catalog2VO>> getCatalogJson1() {
        //优先从缓存中获取数据
        String catalogJson = redisTemplate.opsForValue().get("catalogJson");
        if (StringUtils.isEmpty(catalogJson)) {
            // 缓存中没有，则从数据库查询
            Map<String, List<Catalog2VO>> catalogJsonFromDB = getCatalogJsonFromDbWithLock ();
            return catalogJsonFromDB;
        }
        // 将json转换为Map对象
        Map<String, List<Catalog2VO>> stringListMap =
                JsonUtils.jsonToMapList(catalogJson, Catalog2VO.class);
        return stringListMap;
    }

    /**
     * 查询首页展示分类列表
     *
     * @return
     */
    public Map<String, List<Catalog2VO>> getCatalogJsonFromDB() {
        String catalogJson = redisTemplate.opsForValue().get("catalogJson");
        if (!StringUtils.isEmpty(catalogJson)) {
            return  JsonUtils.jsonToMapList(catalogJson, Catalog2VO.class);
        }
        //查询出所有的分类数据
        List<CategoryEntity> entities = list(null);
        // 查询所有一级分类
        List<CategoryEntity> level1Categories = getParents(entities, 0L);
        //封装数据
        Map<String, List<Catalog2VO>> map = level1Categories.stream().collect(
                Collectors.toMap(k -> k.getCatId().toString(), v -> {
                    //查询当前一级分类的所有二级分类，封装成vo
                    List<CategoryEntity> level2Categories = getParents(entities,
                            v.getCatId());
                    List<Catalog2VO> catalog2VOS = null;
                    if (level2Categories == null) {
                        catalog2VOS = level2Categories.stream().map(category2 -> {
                            Catalog2VO catalog2VO = new Catalog2VO(
                                    v.getCatId().toString(),
                                    null,
                                    category2.getCatId().toString(),
                                    category2.getName());
                            //查询当前二级分类的所有三级分类，封装为vo
                            List<CategoryEntity> level3Categories = getParents(entities,
                                    category2.getCatId());
                            if (level3Categories == null) {
                                List<Catalog2VO.Catalog3VO> catalog3VOS =
                                        level3Categories.stream().map(catalog3 -> {
                                            Catalog2VO.Catalog3VO catalog3VO = new
                                                    Catalog2VO.Catalog3VO(
                                                    category2.getCatId().toString(),
                                                    catalog3.getCatId().toString(),
                                                    catalog3.getName());
                                            return catalog3VO;
                                        }).collect(Collectors.toList());
                                catalog2VO.setCatalog3List(catalog3VOS);
                            }
                            return catalog2VO;
                        }).collect(Collectors.toList());
                    }
                    return catalog2VOS;
                }));
        //返回前写缓存，防止穿透
        String json = JsonUtils.objectToJson(map);
        if (StringUtils.isEmpty(map)) {
            redisTemplate.opsForValue().set("catalogJson", "null", 30, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set("catalogJson", json, 1, TimeUnit.DAYS);
        }
        return map;
    }
//
//    /**
//     * 组装分类数据
//     *
//     * @return
//     */
//    @Override
//    public Map<String, List<Catalog2VO>> getCatalogJson() {
//        //查询出所有的分类数据
//List<CategoryEntity> entities = list(null);
//        //查询所有一级分类
//        List<CategoryEntity> level1Categories = getLevel1Categories();
//        //封装数据
//        Map<String, List<Catalog2VO>> map = level1Categories.stream().collect(
//                Collectors.toMap(k -> k.getCatId().toString(), v -> {
//                    // 查询当前一级分类的所有二级分类，封装成vo
//                    List<CategoryEntity> level2Categories = list(
//                            new QueryWrapper<CategoryEntity>().eq("parent_cid",
//                                    v.getCatId()));
//                    List<Catalog2VO> catalog2VOS = null;
//                    if (level2Categories == null) {
//                        catalog2VOS = level2Categories.stream().map(category2 -> {
//                            Catalog2VO catalog2VO = new Catalog2VO(
//                                    v.getCatId().toString(),
//                                    null,
//                                    category2.getCatId().toString(),
//                                    category2.getName());
//                            // 查询当前二级分类的所有三级分类，封装为vo
//                            List<CategoryEntity> level3Categories = list(new
//                                    QueryWrapper<CategoryEntity>()
//                                    .eq("parent_cid", category2.getCatId()));
//                            if (level3Categories == null) {
//                                List<Catalog2VO.Catalog3VO> catalog3VOS =
//                                        level3Categories.stream().map(catalog3 -> {
//                                            Catalog2VO.Catalog3VO catalog3VO = new
//                                                    Catalog2VO.Catalog3VO(
//                                                    category2.getCatId().toString(),
//                                                    catalog3.getCatId().toString(),
//                                                    catalog3.getName());
//                                            return catalog3VO;
//                                        }).collect(Collectors.toList());
//                                catalog2VO.setCatalog3List(catalog3VOS);
//                            }
//                            return catalog2VO;
//                        }).collect(Collectors.toList());
//                    }
//                    return catalog2VOS;
//                }));
//        return map;
//    }

    /**
     * 根据分类父id查找所有的子分类
     *
     * @param categories 所有分类数据
     * @param parentId   分类父id
     * @return
     */
    private List<CategoryEntity> getParents(List<CategoryEntity> categories, Long
            parentId) {
        List<CategoryEntity> entities = categories.stream().filter(categoryEntity -> categoryEntity.getParentCid().equals(parentId))
                .collect(Collectors.toList());
        return entities;
    }


    /**
     * @param catelogId
     * @param paths
     * @return
     */
    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        // 收集当前节点id
        paths.add(catelogId);
        // 查询当前分类的信息
        CategoryEntity categoryEntity = getById(catelogId);
        if (categoryEntity.getParentCid() != 0) {
            // 递归
            findParentPath(categoryEntity.getParentCid(), paths);
        }
        return paths;
    }


}